/*!
 * JavaScript Library v0.1
 * Copyright 2011-2012, Louis Chen
 * Lastupdatedby Louis Chen 06/Jan/2012 HKT
 *
 */
 


 (function(window, undefined) {
    if (typeof window.Hsbc == "undefined") {
        window.Hsbc = new Object();
    }
    Hsbc.mobile.adaptor = (function() {
        var adaptor = function(options) {
            return new adaptor.fn.init(options);
        };

				/**
				 * For app hook apis
				 *
				 */
				adaptor.app = {
					send : function(locale){
						adaptor.fn.locale = locale;
					}
				};
				
				/**
				 * For adaptor function
				 *
				 */
        adaptor.fn = adaptor.prototype = {
            opt: {	   
            	debug:true,
            	dummy:false,
            	error_back_mappings:null,
            	customerType:'customerType'         				
			      },
            req:null,
            resp:null,
            locale:null,
            common_error_mapping:null,
            error_back_mapping:null,
            common_error_msg:null,
            common_error_backtype:null,
            current_request_obj:null,
            require_stepup_obj:null,
            init: function(options) {
								this.opt = $.extend(this.opt, options);
                this._debug('Hsbc mobile adaptor init');
                return this;
            },
            _debug : function(message){
	            if (window.console !== undefined && this.opt.debug === true) {
	                console.log(message);
	            }            	
            },
            
            initCommonErrorMapping:function(msg)
            {
            	this.common_error_mapping=msg;
            },
						
            execute : function(opts){
            	this.deferred = $.Deferred();
 							this.current_request_obj=opts;
 							String.prototype.startsWith = function(str) {return (this.match("^"+str)==str)};
 							var url=opts.url;
 							if(!url.startsWith("http") && !url.startsWith("https"))
 							{
 							   url=opts.inst.opt.wtSettings.host+url;
 							}
 							this.proxySend(opts.dummyWrapper,opts.inst,opts.datajs,opts.callback,url,opts.method,opts.loadingText,opts.hideLoadingImg);
 							if (this.opt.dummy === true){
	 							var self = this;
	 							this.deferred.done(function(){
	 								  var callback=opts.callback;
	 								  if (typeof callback === "string")
	 								  {
	 								  	 var nameArray=callback.split(".");
	 								  	 var callbackStr=window[nameArray[0]];
	 								  	 for(var i=1;i<nameArray.length;i++)
	 								  	 {
	 								  	 	 callbackStr=callbackStr[nameArray[i]];
	 								  	 }
	 								  	 if($.isFunction(callbackStr))
	 								  	 {
	 								  	  callbackStr(self.resp);
	 								  	 }
	 								  }
	 								  else if(callback && $.isFunction(callback))
	 								  {
	 								  	 callback(self.resp);
	 								  }
	 							});
 						  }
 						},
						
						proxySend : function(req,inst,datajs,callback,url,method,text,hideLoadingImg){
							var self = this;
							$("#ui-loader").find(">div").show();
							if(hideLoadingImg!=undefined && hideLoadingImg!='' && hideLoadingImg==true)
							{
								 $("#ui-loader").find(">div").hide();
						  } 
							if(text!=undefined && text!='')
						     inst.showLoadOverlay(text);
						  else
						     inst.showLoadOverlay();	
						  if (this.opt.dummy === true){
								this._debug("get dummy message");
								$.when(inst.reqr({
									baseUrl : '../../dummy/',
									deferred : self.deferred,
									deps : [req + '.resp'], 
									callback : function(resp){
										self.resp = resp;
									}
								}));
							}
							else{
								//TODO, call app hook proxy api
								inst.proxy(datajs, 
									callback, 
									url, 
									method
								);	
							}
						},
						handleCallback:function(opts){
							//hide loadOcerlay
							opts.inst.hideLoadOverlay();	
							 var self=this;
							 self.common_error_msg='';
							 self.common_error_backtype='';
							 var errorCode='';
							 var handleCommonErr=true;//default
							 if(opts.hasOwnProperty('handleCommonErr')!=undefined && opts.handleCommonErr===false)
							 {
							 	  handleCommonErr=false;
							 }
							 var returnObj={data:null,commonErrMsg:'',commonErrBackType:''};
							 if(opts.json=== undefined||opts.json===null||opts.json==='null')
							 {
							  	errorCode='jsonErr';
							  	self.handleCommonError(errorCode,opts.inst,opts.inst.currentPage,opts.errorPage,opts.errorPageTwo,handleCommonErr);
							  	if(!handleCommonErr)
							 	  {
							 	 	  returnObj.commonErrMsg=self.common_error_msg;
							 	 	  returnObj.commonErrBackType=self.common_error_backtype;
							 	 	  opts.error(returnObj);
							 	  }
							  	return;
							 }		
							 else
							 {
							 	 
							 	 var jsonResp=opts.json;
							 	 if(typeof jsonResp != 'string' && typeof jsonResp =='object')
							 	 {
							 	 	  jsonResp=jsonResp.toString();
							   }
							   var startTag='<json>';
							 	 var endTag='</json>';
							 	 var json_start_index=jsonResp.indexOf(startTag);
							   var json_end_index=jsonResp.indexOf(endTag);
							   var errorDesc;
							 	 if(json_start_index!=-1 && json_end_index!=-1)
							 	 {
								 		errorDescCode=jsonResp.substring(json_start_index+startTag.length,json_end_index);
								 		var errorMsg='';
								 		if(errorDescCode=='')
								 		{
								 			errorMsg=self.common_error_mapping['noService'];
								 		}
								 		else
								 		{
									 		var jsonTagParser=self.transformJSONString(errorDescCode);
											var jsonTagData=jsonTagParser.data;
											if(!jsonTagParser.valid)
											{
												 errorMsg=self.common_error_mapping['noService'];
									   	}
									   	else
									   	{
									   		  if(jsonTagData!=''&&jsonTagData.hasOwnProperty('header')&&jsonTagData.header.hasOwnProperty('statusCode'))
									    	  {
									    	  	 var statusCode=jsonTagData.header.statusCode;
													   if(jsonTagData.hasOwnProperty('body')&& jsonTagData.header.hasOwnProperty('errorMsg') && jsonTagData.header.errorMsg.length>0)
													   {
													   	 var msg=jsonTagData.header.errorMsg;
													   	 for(var i=0;i<msg.length;i++){
													   	 	   errorMsg += msg[i].desc;
															  }
													   }
												     if(errorMsg=='')
															{
																  if(statusCode=='C001'||statusCode=='C005'||statusCode=='P001'||statusCode=='P002'||statusCode=='P003'||statusCode=='P004')
																  {
																    errorMsg=self.common_error_mapping[statusCode];
																  }
																  else
																  {
																  	errorMsg=self.common_error_mapping['noService'];
															 	  }
															}
											 		}
											 		else
									   		  {
									   		  	errorMsg=self.common_error_mapping['noService'];
									   		  }
									 	  }
									 	}
								 		self.handleCommonErrorBackToApp(opts.inst,opts.inst.currentPage,opts.errorPage,errorMsg);
								 		return;
								 }
							 }	 
							 var jsonParser=self.transformJSONString(opts.json);
							 var data=jsonParser.data;
							 returnObj.data=data;
							 if(!jsonParser.valid)
							 {
							 	 errorCode='jsonErr';
							 	 self.handleCommonError(errorCode,opts.inst,opts.inst.currentPage,opts.errorPage,opts.errorPageTwo,handleCommonErr);
							 	 if(!handleCommonErr)
							 	 {
							 	 	 returnObj.commonErrMsg=self.common_error_msg;
							 	 	 returnObj.commonErrBackType=self.common_error_backtype;
							 	 	 opts.error(returnObj);
							 	 }
							 	 return;
							 }
							
							 if(!data.hasOwnProperty('header') || typeof data.header != 'object' )
							 {
							 	 errorCode='headerErr';
							 	 self.handleCommonError(errorCode,opts.inst,opts.inst.currentPage,opts.errorPage,opts.errorPageTwo,handleCommonErr);
							 	 if(!handleCommonErr)
							 	 {
							 	 	 returnObj.commonErrMsg=self.common_error_msg;
							 	 	 returnObj.commonErrBackType=self.common_error_backtype;
							 	 	 opts.error(returnObj);
							 	 }
							 	 return;
						   } 
						   else
						   {
						   	 if(!data.header.hasOwnProperty('statusCode')||data.header.statusCode===''||data.header.statusCode==='null'
						   	 || typeof data.header.statusCode != 'string')
						     {
						     	 errorCode='statusCodeErr';
								 	 self.handleCommonError(errorCode,opts.inst,opts.inst.currentPage,opts.errorPage,opts.errorPageTwo,handleCommonErr);
								 	 if(!handleCommonErr)
							 	   {
							 	 	 returnObj.commonErrMsg=self.common_error_msg;
							 	 	 returnObj.commonErrBackType=self.common_error_backtype;
							 	 	 opts.error(returnObj);
							 	   }
								 	 return;
						     }
						     else
						     {
						     	 errorCode=data.header.statusCode;
						     }
						   }
						   //step required
						   
						   if(errorCode=='C003')
						   {
						   	 self.goToStepup(opts.inst);
						   	 return;
						   }
						   
						  
							 if(self.handleCommonError(errorCode,opts.inst,opts.inst.currentPage,opts.errorPage,opts.errorPageTwo,handleCommonErr,data))
							 {
							 	 if(!handleCommonErr)
							 	 {
							 	 	 returnObj.commonErrMsg=self.common_error_msg;
							 	 	 returnObj.commonErrBackType=self.common_error_backtype;
							 	 	 opts.error(returnObj);
							 	 }
							 	 return;
							 }
							 if(self.isExistSpecialError(errorCode))
							 {
							 	  opts.error(returnObj);
							 	  return;
							 }
							 require([opts.adaptor],function(resp){
					         var rs = opts.inst.adaptRegister(data,{
								    'type' : 'object',
								    'properties' : resp
							     });	
							    if(rs.valid && rs.errors.length==0)
							    {
							     opts.success(returnObj);
							    }
							    else
							    {
							    	if(!handleCommonErr)
							    	{
							    		 var errorMsg='';
							    		 var errors=rs.errors;
										   for(i in errors)
										   {
										 	  errorMsg+=errors[i].property+":"+errors[i].message+"<br/>";
										   }
										   self.common_error_msg=errorMsg;
										   returnObj.commonErrMsg=self.common_error_msg;
									 	 	 opts.error(returnObj);
							    	}
							    	else
							    	{
							    	   self.handleAdaptorError(rs.errors,opts.inst,opts.inst.currentPage,opts.errorPage,opts.errorPageTwo);
							      }
							    }
							 });	
						},
						transformJSONString : function(data){	
							   var rs={data:data,valid:false};
							   if(this.opt.dummy){
							   	  rs.data=data;
							   	  rs.valid=true;
								    return rs;
		             }
		             else
		             {
									 try{
										  data =  $.parseJSON(data);
										  rs.valid=true;
										  rs.data=data;
										 }
										 catch(err){
									   // handle server error parseJSONError
									 	 return rs;
									   }
									 return rs;		
							  }					
						},
						handleCommonError:function(errorCode,inst,fromPage,errorPage_one,errorPage_two,handleCommonErr,data)
						{
							 var self=this;
							 
							 if(self.common_error_mapping[errorCode])
						   { 
						  
						      var errorMsg='';
							    if(data!=undefined)
					    	  {
									   if(data.hasOwnProperty('body')&& data.header.hasOwnProperty('errorMsg') && data.header.errorMsg.length>0)
									   {
									   	 var msg=data.header.errorMsg;
									   	 for(var i=0;i<msg.length;i++){
									   	 	   errorMsg += msg[i].desc;
											 }
									   }
								  }
									if(errorMsg=='')
									{
										  if(errorCode=='C001'||errorCode=='C005'||errorCode=='P001'||errorCode=='P002'||errorCode=='P003'||errorCode=='P004')
										  {
										    errorMsg=self.common_error_mapping[errorCode];
										  }
										  else
										  {
										  	errorMsg=self.common_error_mapping['noService'];
									 	  }
									}
						   	  if(!handleCommonErr)
						   	  {
						   	  	 self.common_error_msg=errorMsg;
						   	     self.common_error_backtype=self.opt.error_back_mapping[errorCode]
						   	  	 return true;
						   	  }
						   	  if(self.opt.error_back_mapping[errorCode]==='backToApp')
							    {
							    	 $(errorPage_one).find(".error-panel").find("p").html(errorMsg);
							       inst.goTo({'from':fromPage,'to':errorPage_one});
							    	 self.errorBackToApp(inst,errorPage_one);
							    }
							    else
							    {
							    	self.handleErrorBackToPage(inst,fromPage,errorPage_one,errorPage_two,errorMsg);
							    }
							    return true;
						   }
						   else
						   {
						   	  return false;
						   }
						},
					  isExistSpecialError:function(errorCode)
						{
							 var self=this;
							 if(errorCode!="0000" && typeof self.common_error_mapping[errorCode]=='undefined')
							 {
						     return true;
						   }
						   else 
						   {
						   	 return false;
						   }
						},
						handleSpecialError:function(inst,fromPage,errorPage,errorMsg)
						{
							 var self=this;
							 inst.goTo({'from':fromPage,'to':errorPage});
							 if(errorMsg=='')
						   {
						     errorMsg=self.common_error_mapping['noService'];
						   }
						   $(errorPage).find(".error-panel").find("p").html(errorMsg);
						   self.errorGoBack(inst,errorPage); 
						},
						handleCommonErrorBackToApp:function(inst,fromPage,errorPage,errorMsg)
						{
							 var self=this;
							 inst.goTo({'from':fromPage,'to':errorPage});
						   $(errorPage).find(".error-panel").find("p").html(errorMsg);
						   if(errorMsg=='')
						   {
						     errorMsg=self.common_error_mapping['noService'];
						   }
						   self.errorBackToApp(inst,errorPage); 
						},
						handleAdaptorError:function(errors,inst,fromPage,errorPage,errorPage_two)
						{
							 var self=this;
							 var errorMsg='';
							 for(i in errors)
							 {
								 errorMsg+=errors[i].property+":"+errors[i].message+"<br/>";
							 }
							 if(errorMsg=='')
						   {
						     errorMsg=self.common_error_mapping['noService'];
						   }
							 return self.handleErrorBackToPage(inst,fromPage,errorPage,errorPage_two,errorMsg);
						},
						handleErrorBackToPage:function(inst,fromPage,errorPage_one,errorPage_two,errorMsg)
						{
							 var self=this;
							 inst.goTo({'from':fromPage,'to':errorPage_one});
							 if(errorMsg=='')
						   {
						     errorMsg=self.common_error_mapping['noService'];
						   }
						   $(errorPage_one).find(".error-panel").find("p").html(errorMsg);
						   if(errorPage_two!==undefined && errorPage_two!='')
						   {
						      self.errorBackToPage(inst,errorPage_one,errorPage_two,errorMsg);
						   }
						   else
						   {
						   	  self.errorGoBack(inst,errorPage_one);
						   }
						},
						errorBackToApp:function(inst,errorPage)
						{
							 $(errorPage).find('.ui-back').hide();
							 var ok_btn=$(errorPage).find('.ui-btn-next');
							 ok_btn.show();
							 ok_btn.unbind('click');
							 ok_btn.click(function(){
							    inst.backToApp(inst.locale,"home");	
							 });
					  },
					  errorBackToPage:function(inst,errorPage_one,errorPage_two,errorMsg)
						{
							 $(errorPage_one).find('.ui-back').hide();
							 var ok_btn=$(errorPage_one).find('.ui-btn-next');
							 ok_btn.show();
							 ok_btn.unbind('click');
               ok_btn.click(function(){
							     inst.goBack({'from':errorPage_one,'to':errorPage_two});	
							     $(errorPage_two).find(".error-panel").find("p").html(errorMsg);
							 });
					  },
					  errorGoBack:function(inst,errorPage)
						{
							 $(errorPage).find('.ui-btn-next').hide();
							 var back_btn=$(errorPage).find('.ui-back');
							 back_btn.show();
							 back_btn.unbind('click');
               back_btn.click(function(){
							    inst.goBack();	
							 });
					  },
					  updateErrorMsg:function(errorPage,errorMsg)
						{
							var self=this;
							if(errorMsg=='')
							{
								errorMsg=self.common_error_mapping['noService'];
							}
							 $(errorPage).find(".error-panel").find("p").html(errorMsg);
					  },
					  customerTypeSetter:function(inst,dataJs,callbackJs)
					  {
					  	 inst.setter(this.opt.customerType,dataJs,callbackJs);
					  },
					  customerTypeGetter:function(inst,callbackJs)
					  {
					  	 inst.getter(this.opt.customerType,callbackJs);
					  },
					  goToStepup:function(inst)
					  {
					  	
					  	this.require_stepup_obj=this.current_request_obj;
					  	inst.goTo({'from':inst.currentPage,'to':'#stepupCam40'});
					 }
				}		
						
        //
        // Give the init function the hsbcMobile prototype for later instantiation
        adaptor.fn.init.prototype = adaptor.fn;

        return adaptor;
    })();

    // Expose hsbc mobile as an AMD module, but only for AMD loaders.
    if (typeof define === "function" && define.amd && define.amd.Hsbc) {
        define("jsonadaptor", [],
        function() {
            return Hsbc.mobile.adaptor;
        });
    }
})(window);